/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ssp.strategy.factory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import ssp.service.FrontendServer;
import ssp.service.FrontendServerManager;
import ssp.service.ServiceEntry;
import ssp.service.ServiceEntryPool;
import ssp.utility.MersenneTwisterRNG;

/**
 *
 * @author yamazaki
 */
public class CreateServiceEntryStrategy {
    
    /**
     * 各フロントエンドサーバにentryNumずつのServiceEntryを割り当てる
     * @param typeNum
     * @param entryNum
     * @param QoSnum
     * @param QoSrange 
     */
    public static void allocateFlatTypeNum(int typeNum, int entryNum, int QoSnum, int QoSrange) {
        List<Integer> typeIndexList = new ArrayList<>();
        for (int i=0 ; i<typeNum ; i++) {
            typeIndexList.add(i);
        }
        LinkedList<Integer> shuffledList = new LinkedList<>();
        for (FrontendServer frontendServer : FrontendServerManager.getINSTANCE().getFrontendServerList()) {
            for (int i = 0; i < entryNum; i++) {
                if (shuffledList.isEmpty()) {
                    Collections.shuffle(typeIndexList, MersenneTwisterRNG.getINSTANCE());
                    shuffledList.addAll(typeIndexList);
                    Collections.sort(typeIndexList);
                }
                List<Integer> qos = new ArrayList<>(makeQoS(QoSnum, QoSrange));
                ServiceEntry entry = new ServiceEntry(shuffledList.poll(), makeWorkload(qos), qos, makeCharge(qos));
                ServiceEntryPool.getINSTANCE().add(entry);
                frontendServer.addServiceEntry(entry);
            }
        }
    }
    
     /**
     * 指定数のQoS指標を生成
     * @param QoSnum QoSの数
     * @param QoSrange QoSの幅
     * @return 
     */
    private static List<Integer> makeQoS(int QoSnum, int QoSrange) {
        List<Integer> QoSindexList = new ArrayList<>();
        for(int i=0 ; i<QoSnum ; i++) {
            QoSindexList.add(MersenneTwisterRNG.getINSTANCE().nextInt(QoSrange) + 1);
        }
        return QoSindexList;
    }
    
    /**
     * QoS指標からサービスの処理負荷を生成する
     * @param QoSindexlist QoS指標のリスト
     * @return サービス処理負荷
     */
    private static double makeWorkload(List<Integer> QoSindexlist) {
        double workload = 0.0;
        for(int qos : QoSindexlist) {
            workload += qos * MersenneTwisterRNG.getINSTANCE().nextDouble();
        }
        return workload;
    }
    
    /**
     * QoS指標から利用料金を生成する
     * @param QoSindexlist QoS指標のリスト
     * @return サービス使用料金
     */
    private static double makeCharge(List<Integer> QoSindexlist) {
        double charge = MersenneTwisterRNG.getINSTANCE().nextDouble() * 70.0 * 1.0;
        for(int qos : QoSindexlist) {
            charge += qos * MersenneTwisterRNG.getINSTANCE().nextDouble() * 70.0 * 1.0;
        }
        return charge;
    }
    
}
